# -*- coding: utf-8 -*-
# @Date：2024/7/31 11:59:14
# @Author：CJiaの青姝
# @FileName：role
# @Editor：PyCharm2024
# @Remark：
from typing import List, Any
from typing_extensions import Self

from system.models import Role, RoleMenu, RoleMenuItem, MenuButton
from ninja import Router, Field, File, Query, Schema, ModelSchema
from ninja import Router
from ninja.files import UploadedFile
from ninja.pagination import paginate

from utils.cj_ninja import CjFilters, MyPagination
from utils.cj_crud import create, batch_create, delete, batch_delete, update, condition, single
from utils.cj_export import export_data, repeat_data, deal_chinese_key
from utils.cj_response import SuccessResponse, ErrorResponse

router = Router()


class Filters(CjFilters):
    name: str = Field(None, description="角色名称", alias='name')
    code: str = Field(None, description="角色编码", alias='code')

    class Config:
        title = "角色查询参数"


class RoleSchemaIn(ModelSchema):

    def validate(cls, value: Any) -> Self:
        if value.name == '' or value.name is None:
            return "角色名称不能为空", 400
        elif value.code == '' or value.code is None:
            return "角色编码不能为空", 400
        # 返回请求数据
        return value, 200

    def model_validate(
            cls,
            obj: Any,
            *,
            strict: bool | None = None,
            from_attributes: bool | None = None,
            context: Any | None = None,
    ) -> Self:
        if obj.name == '' or obj.name is None:
            return "角色名称不能为空", 400
        elif obj.code == '' or obj.code is None:
            return "角色编码不能为空", 400
        # 判断重复
        if Role.objects.filter(name=obj.name).exists():
            return "角色名称已存在，请重新输入", 400
        if Role.objects.filter(code=obj.code).exists():
            return "角色编码已存在，请重新输入", 400
        # 返回请求数据
        return obj, 200

    class Config:
        title = '创建角色参数'
        model = Role
        model_exclude = ['id', 'creator', 'modifier', 'create_time', 'update_time']


class RolePermissionSchemaIn(Schema):
    permissions: List[str] = Field(..., description="权限id列表", alias='permissions')


class RoleSchemaOut(ModelSchema):
    key: int = Field(None, description="唯一标识符", alias='key')

    class Config:
        title = '角色对象实例'
        model = Role
        model_fields = "__all__"


class RoleMenuSchemaOut(ModelSchema):
    key: int = Field(None, description="唯一标识符", alias='key')

    class Config:
        title = '角色菜单对象实例'
        model = RoleMenu
        model_fields = "__all__"


class RoleMenuItemSchemaOut(ModelSchema):
    key: int = Field(None, description="唯一标识符", alias='key')

    class Config:
        title = '角色菜单权限对象实例'
        model = RoleMenuItem
        model_fields = "__all__"


@router.post("/role", summary="创建角色")
def create_role(request, data: RoleSchemaIn):
    """ 创建角色 """
    message, code = data.model_validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 调用新增方法
    result = create(request, Role, message)
    # 返回结果
    return SuccessResponse(data=result, msg="新增成功")


@router.post("/role/export", summary="导入角色")
def export_role(request, file: UploadedFile = File(...)):
    """ 导入角色 """
    # 字段关系
    field_relations = {
        "角色名称": "name",
        "角色编码": "code",
    }
    # 检查字段
    check_list = ["角色名称", "角色编码"]
    # 调用公共导入方法
    export_result = export_data(request, file, check_list)
    # 重复字段
    repeat_filed = [
        {"name": "角色名称", "field": "name", "model": "name"},
        {"name": "角色编码", "field": "code", "model": "code"},
    ]
    # 判断重复
    result = repeat_data(Role, export_result['success'], repeat_filed, False)
    # 处理中文key
    result = deal_chinese_key(result, field_relations)
    # 调用批量新增方法
    result_list = batch_create(request, Role, result['success'])
    Role.objects.bulk_create(result_list)
    message = f"成功导入{len(result_list)}条数据，失败信息{export_result['error'] + result['error']}"
    # 返回结果
    return SuccessResponse(data=result['success'], msg=message)


@router.delete("/role/{role_id}", response=RoleSchemaOut, summary="删除角色")
def delete_role(request, role_id: int):
    """ 删除角色 """
    # 调用删除方法
    result, code = delete(Role, role_id)
    if code != 200:
        return ErrorResponse(code=code, msg=result)
    # 返回结果
    return SuccessResponse(data=result, msg="删除成功")


@router.delete("/role/batch/del", summary="批量删除角色")
def batch_delete_role(request, ids: List[int]):
    """ 批量删除角色 """
    # 调用批量删除方法
    result = batch_delete(request, Role, ids)
    # 返回结果
    return SuccessResponse(data=result, msg="批量删除成功")


@router.put("/role/{role_id}", summary="更新角色")
def update_role(request, role_id: int, data: RoleSchemaIn):
    """ 更新角色 """
    message, code = data.validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 判断重复
    if Role.objects.filter(name=message.name).exists():
        if Role.objects.get(name=message.name).id != role_id:
            return ErrorResponse(msg="角色名称已存在，请重新输入")
    if Role.objects.filter(code=message.code).exists():
        if Role.objects.get(code=message.code).id != role_id:
            return ErrorResponse(msg="角色编码已存在，请重新输入")
    # 调用修改方法
    result = update(request, Role, message, role_id)
    # 返回结果
    return SuccessResponse(data=result, msg="更新成功")


@router.put("/role/permission/{role_id}", response=List[RoleMenuItemSchemaOut], summary="更新角色菜单权限")
def update_role_permission(request, role_id: int, data: RolePermissionSchemaIn):
    """ 更新角色菜单权限 """
    # 菜单
    menus = []
    # 按钮
    buttons = []
    # 循环id
    for permission in data.permissions:
        # 判断是菜单还是按钮
        menu_button = MenuButton.objects.filter(id=permission).first()
        if menu_button:
            # 删除全部按钮
            button_ids = RoleMenuItem.objects.filter(role_id=role_id)
            for button in button_ids:
                delete(RoleMenuItem, button.id)
            # 添加新按钮
            buttons.append({"role_id": role_id, "menu_button_id": permission})
        else:
            # 删除全部菜单
            menu_ids = RoleMenu.objects.filter(role_id=role_id).values_list('id', flat=True)
            for menu in menu_ids:
                delete(RoleMenu, menu)
            # 添加菜单
            menus.append({"role_id": role_id, "menu_id": permission})
    for menu in menus:
        create(request, RoleMenu, menu)
    for button in buttons:
        create(request, RoleMenuItem, button)
    # 获取角色菜单权限列表
    result = list(RoleMenuItem.objects.filter(role_id=role_id).values())
    # 返回结果
    return SuccessResponse(data=result, msg="更新权限成功")


@router.get("/role", response=List[RoleSchemaOut], summary="获取分页角色列表")
@paginate(MyPagination)
def list_role(request, filters: Filters = Query(...)):
    """ 获取分页角色列表 """
    # 调用分页方法
    result = condition(request, Role, filters)
    # 返回结果
    return result


@router.get("/role/list/all", summary="获取角色全部列表")
def list_role_list(request, filters: Filters = Query(...)):
    """ 获取角色全部列表 """
    # 获取角色全部列表
    result = list(Role.objects.all().values("id", "name"))
    # 返回结果
    return SuccessResponse(data=result)


@router.get("/roleMenu/{role_id}", response=List[RoleMenuSchemaOut], summary="获取角色菜单列表")
def list_role_menu(request, role_id: int):
    """ 获取角色菜单列表 """
    # 获取角色菜单列表
    result = list(RoleMenu.objects.filter(role_id=role_id).values())
    # 返回结果
    return SuccessResponse(data=result)


@router.get("/roleMenuItem/{role_id}", response=List[RoleMenuItemSchemaOut], summary="获取角色菜单权限列表")
def list_role_menu_button(request, role_id: int):
    """ 获取角色菜单权限列表 """
    # 获取角色菜单权限列表
    result = list(RoleMenuItem.objects.filter(role_id=role_id).values())
    # 返回结果
    return SuccessResponse(data=result)


@router.get("/role/{role_id}", response=RoleSchemaOut, summary="获取角色")
def get_role(request, role_id: int):
    """ 获取角色 """
    # 调用根据id获取指定对象方法
    result = single(request, Role, id=role_id)
    # 返回结果
    return SuccessResponse(data=result)
